home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999, 2000 Aladdin Enterprises. All rights reserved.
-
- This file is part of AFPL Ghostscript.
-
- AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or
- distributor accepts any responsibility for the consequences of using it, or
- for whether it serves any particular purpose or works at all, unless he or
- she says so in writing. Refer to the Aladdin Free Public License (the
- "License") for full details.
-
- Every copy of AFPL Ghostscript must include a copy of the License, normally
- in a plain ASCII text file named PUBLIC. The License grants you the right
- to copy, modify and redistribute AFPL Ghostscript, but only under certain
- conditions described in the License. Among other things, the License
- requires that the copyright notice and this notice be preserved on all
- copies.
- */
-
- /*$Id: gp_os2.c,v 1.4.2.1 2000/12/05 01:31:14 raph Exp $ */
- /* Common platform-specific routines for OS/2 and MS-DOS */
- /* compiled with GCC/EMX */
-
- #define INCL_DOS
- #define INCL_SPL
- #define INCL_SPLDOSPRINT
- #define INCL_SPLERRORS
- #define INCL_BASE
- #define INCL_ERRORS
- #define INCL_WIN
- #include <os2.h>
-
- #include "pipe_.h"
- #include "stdio_.h"
- #include "string_.h"
- #include <fcntl.h>
-
- #ifdef __IBMC__
- #define popen fopen /* doesn't support popen */
- #define pclose fclose /* doesn't support pclose */
- #else
- #include <dos.h>
- #endif
- /* Define the regs union tag for short registers. */
- # define rshort x
- #define intdos(a,b) _int86(0x21, a, b)
-
- #include "memory_.h"
- #include "string_.h"
- #include "gx.h"
- #include "gsexit.h"
- #include "gsmemory.h"
- #include "gsstruct.h"
- #include "gp.h"
- #include "gpmisc.h"
- #include "gsutil.h"
- #include "stdlib.h" /* need _osmode, exit */
- #include "time_.h"
- #include <time.h> /* should this be in time_.h? */
- #include "gdevpm.h"
- #ifdef __EMX__
- #include <sys/emxload.h>
- #endif
-
- #if defined(__DLL__) && defined( __EMX__)
- /* This isn't provided in any of the libraries */
- /* We set this to the process environment in gp_init */
- char *fake_environ[3] =
- {"", NULL, NULL};
- char **environ = fake_environ;
- char **_environ = fake_environ;
- HWND hwndtext = (HWND) NULL;
-
- #endif
-
- #ifdef __DLL__
- /* use longjmp instead of exit when using DLL */
- #include <setjmp.h>
- extern jmp_buf gsdll_env;
-
- #endif
-
- #ifdef __DLL__
- #define isos2 TRUE
- #else
- #define isos2 (_osmode == OS2_MODE)
- #endif
- char pm_prntmp[256]; /* filename of printer spool temporary file */
-
-
- /* ------ Miscellaneous ------ */
-
- /* Get the string corresponding to an OS error number. */
- /* All reasonable compilers support it. */
- const char *
- gp_strerror(int errnum)
- {
- return strerror(errnum);
- }
-
- /* use Unix version for date and time */
- /* ------ Date and time ------ */
-
- /* Read the current time (in seconds since Jan. 1, 1970) */
- /* and fraction (in nanoseconds since midnight). */
- void
- gp_get_realtime(long *pdt)
- {
- struct timeval tp;
- struct timezone tzp;
-
- if (gettimeofday(&tp, &tzp) == -1) {
- lprintf("Ghostscript: gettimeofday failed!\n");
- gs_exit(1);
- }
- /* tp.tv_sec is #secs since Jan 1, 1970 */
- pdt[0] = tp.tv_sec;
- pdt[1] = tp.tv_usec * 1000;
-
- #ifdef DEBUG_CLOCK
- printf("tp.tv_sec = %d tp.tv_usec = %d pdt[0] = %ld pdt[1] = %ld\n",
- tp.tv_sec, tp.tv_usec, pdt[0], pdt[1]);
- #endif
- }
-
- /* Read the current user CPU time (in seconds) */
- /* and fraction (in nanoseconds). */
- void
- gp_get_usertime(long *pdt)
- {
- gp_get_realtime(pdt); /* Use an approximation for now. */
- }
-
-
- /* ------ Console management ------ */
-
- /* Answer whether a given file is the console (input or output). */
- /* This is not a standard gp procedure, */
- /* but the MS Windows configuration needs it, */
- /* and other MS-DOS configurations might need it someday. */
- /* Don't know if it is needed for OS/2. */
- bool
- gp_file_is_console(FILE * f)
- {
- #ifndef __DLL__
- if (!isos2) {
- union REGS regs;
-
- if (f == NULL)
- return false;
- regs.h.ah = 0x44; /* ioctl */
- regs.h.al = 0; /* get device info */
- regs.rshort.bx = fileno(f);
- intdos(®s, ®s);
- return ((regs.h.dl & 0x80) != 0 && (regs.h.dl & 3) != 0);
- }
- #endif
- if ((f == gs_stdin) || (f == gs_stdout) || (f == gs_stderr))
- return true;
- return false;
- }
-
- /* ------ File naming and accessing ------ */
-
- /* Define the character used for separating file names in a list. */
- const char gp_file_name_list_separator = ';';
-
- /* Define the default scratch file name prefix. */
- const char gp_scratch_file_name_prefix[] = "gs";
-
- /* Define the name of the null output file. */
- const char gp_null_file_name[] = "nul";
-
- /* Define the name that designates the current directory. */
- const char gp_current_directory_name[] = ".";
-
- /* Define the string to be concatenated with the file mode */
- /* for opening files without end-of-line conversion. */
- const char gp_fmode_binary_suffix[] = "b";
-
- /* Define the file modes for binary reading or writing. */
- const char gp_fmode_rb[] = "rb";
- const char gp_fmode_wb[] = "wb";
-
- /* Answer whether a file name contains a directory/device specification, */
- /* i.e. is absolute (not directory- or device-relative). */
- bool
- gp_file_name_is_absolute(const char *fname, uint len)
- { /* A file name is absolute if it contains a drive specification */
- /* (second character is a :) or if it start with 0 or more .s */
- /* followed by a / or \. */
- if (len >= 2 && fname[1] == ':')
- return true;
- while (len && *fname == '.')
- ++fname, --len;
- return (len && (*fname == '/' || *fname == '\\'));
- }
-
- /* Answer the string to be used for combining a directory/device prefix */
- /* with a base file name. The file name is known to not be absolute. */
- const char *
- gp_file_name_concat_string(const char *prefix, uint plen,
- const char *fname, uint len)
- {
- if (plen > 0)
- switch (prefix[plen - 1]) {
- case ':':
- case '/':
- case '\\':
- return "";
- };
- return "\\";
- }
-
-
- /* ------ File enumeration ------ */
-
-
- struct file_enum_s {
- FILEFINDBUF3 findbuf;
- HDIR hdir;
- char *pattern;
- int patlen; /* orig pattern length */
- int pat_size; /* allocate space for pattern */
- int head_size; /* pattern length through last */
- /* :, / or \ */
- int first_time;
- gs_memory_t *memory;
- };
- gs_private_st_ptrs1(st_file_enum, struct file_enum_s, "file_enum",
- file_enum_enum_ptrs, file_enum_reloc_ptrs, pattern);
-
- /* Initialize an enumeration. may NEED WORK ON HANDLING * ? \. */
- file_enum *
- gp_enumerate_files_init(const char *pat, uint patlen, gs_memory_t * mem)
- {
- file_enum *pfen = gs_alloc_struct(mem, file_enum, &st_file_enum, "gp_enumerate_files");
- int pat_size = 2 * patlen + 1;
- char *pattern;
- int hsize = 0;
- int i;
-
- if (pfen == 0)
- return 0;
-
- /* pattern could be allocated as a string, */
- /* but it's simpler for GC and freeing to allocate it as bytes. */
-
- pattern = (char *)gs_alloc_bytes(mem, pat_size,
- "gp_enumerate_files(pattern)");
- if (pattern == 0)
- return 0;
- memcpy(pattern, pat, patlen);
- /* find directory name = header */
- for (i = 0; i < patlen; i++) {
- switch (pat[i]) {
- case '\\':
- if (i + 1 < patlen && pat[i + 1] == '\\')
- i++;
- /* falls through */
- case ':':
- case '/':
- hsize = i + 1;
- }
- }
- pattern[patlen] = 0;
- pfen->pattern = pattern;
- pfen->patlen = patlen;
- pfen->pat_size = pat_size;
- pfen->head_size = hsize;
- pfen->memory = mem;
- pfen->first_time = 1;
- pfen->hdir = HDIR_CREATE;
- return pfen;
- }
-
- /* Enumerate the next file. */
- uint
- gp_enumerate_files_next(file_enum * pfen, char *ptr, uint maxlen)
- {
- APIRET rc;
- ULONG cFilenames = 1;
-
- if (!isos2) {
- /* CAN'T DO IT SO JUST RETURN THE PATTERN. */
- if (pfen->first_time) {
- char *pattern = pfen->pattern;
- uint len = strlen(pattern);
-
- pfen->first_time = 0;
- if (len > maxlen)
- return maxlen + 1;
- strcpy(ptr, pattern);
- return len;
- }
- return -1;
- }
- /* else OS/2 */
- if (pfen->first_time) {
- rc = DosFindFirst(pfen->pattern, &pfen->hdir, FILE_NORMAL,
- &pfen->findbuf, sizeof(pfen->findbuf),
- &cFilenames, FIL_STANDARD);
- pfen->first_time = 0;
- } else {
- rc = DosFindNext(pfen->hdir, &pfen->findbuf, sizeof(pfen->findbuf),
- &cFilenames);
- }
- if (rc)
- return -1;
-
- if (pfen->head_size + pfen->findbuf.cchName < maxlen) {
- memcpy(ptr, pfen->pattern, pfen->head_size);
- strcpy(ptr + pfen->head_size, pfen->findbuf.achName);
- return pfen->head_size + pfen->findbuf.cchName;
- }
- if (pfen->head_size >= maxlen)
- return 0; /* no hope at all */
-
- memcpy(ptr, pfen->pattern, pfen->head_size);
- strncpy(ptr + pfen->head_size, pfen->findbuf.achName,
- maxlen - pfen->head_size - 1);
- return maxlen;
- }
-
- /* Clean up the file enumeration. */
- void
- gp_enumerate_files_close(file_enum * pfen)
- {
- gs_memory_t *mem = pfen->memory;
-
- if (isos2)
- DosFindClose(pfen->hdir);
- gs_free_object(mem, pfen->pattern,
- "gp_enumerate_files_close(pattern)");
- gs_free_object(mem, pfen, "gp_enumerate_files_close");
- }
-
- /*************************************************************/
- /* from gp_iwatc.c and gp_itbc.c */
-
- /* Intel processor, EMX/GCC specific routines for Ghostscript */
- #include <signal.h>
- #include "stat_.h"
- #include "string_.h"
-
- /* Library routines not declared in a standard header */
- /* extern char *getenv(P1(const char *)); */
-
- /* Forward declarations */
- private void handle_FPE(P1(int));
-
- /* Do platform-dependent initialization. */
- void
- gp_init(void)
- {
- #if defined(__DLL__) && defined(__EMX__)
- PTIB pptib;
- PPIB pppib;
- int i;
- char *p;
-
- /* get environment of EXE */
- DosGetInfoBlocks(&pptib, &pppib);
- for (i = 0, p = pppib->pib_pchenv; *p; p += strlen(p) + 1)
- i++;
- _environ = environ = (char **)malloc((i + 2) * sizeof(char *));
-
- for (i = 0, p = pppib->pib_pchenv; *p; p += strlen(p) + 1) {
- environ[i] = p;
- i++;
- }
- environ[i] = p;
- i++;
- environ[i] = NULL;
- #endif
-
- /* keep gsos2.exe in memory for number of minutes specified in */
- /* environment variable GS_LOAD */
- #ifdef __EMX__
- _emxload_env("GS_LOAD");
- #endif
-
- /* Set up the handler for numeric exceptions. */
- signal(SIGFPE, handle_FPE);
- }
-
-
- /* Trap numeric exceptions. Someday we will do something */
- /* more appropriate with these. */
- private void
- handle_FPE(int sig)
- {
- eprintf("Numeric exception:\n");
- exit(1);
- }
-
- extern int gs_exit_status;
-
- /* Do platform-dependent cleanup. */
- void
- gp_exit(int exit_status, int code)
- {
- #ifndef __DLL__
- if (exit_status && (_osmode == OS2_MODE))
- DosSleep(2000);
- #endif
- #if defined(__DLL__) && defined(__EMX__)
- if (environ != fake_environ) {
- free(environ);
- environ = _environ = fake_environ;
- }
- #endif
- }
-
- /* Exit the program. */
- void
- gp_do_exit(int exit_status)
- {
- #if defined(__DLL__)
- /* Use longjmp since exit would terminate caller */
- /* setjmp code will check gs_exit_status */
- longjmp(gsdll_env, gs_exit_status);
- #else
- exit(exit_status);
- #endif
- }
-
- /* ------ Printer accessing ------ */
- private int pm_find_queue(char *queue_name, char *driver_name);
- private int is_os2_spool(const char *queue);
- private int pm_spool(char *filename, const char *queue);
-
- /* Put a printer file (which might be stdout) into binary or text mode. */
- /* This is not a standard gp procedure, */
- /* but all MS-DOS configurations need it. */
- void
- gp_set_file_binary(int prnfno, int binary)
- {
- #ifndef __IBMC__
- union REGS regs;
-
- regs.h.ah = 0x44; /* ioctl */
- regs.h.al = 0; /* get device info */
- regs.rshort.bx = prnfno;
- intdos(®s, ®s);
- if (((regs.rshort.flags) & 1) != 0 || !(regs.h.dl & 0x80))
- return; /* error, or not a device */
- if (binary)
- regs.h.dl |= 0x20; /* binary (no ^Z intervention) */
- else
- regs.h.dl &= ~0x20; /* text */
- regs.h.dh = 0;
- regs.h.ah = 0x44; /* ioctl */
- regs.h.al = 1; /* set device info */
- intdos(®s, ®s);
- #endif
- }
-
- /* Open a connection to a printer. A null file name means use the */
- /* standard printer connected to the machine, if any. */
- /* Return NULL if the connection could not be opened. */
- /* filename can be one of the following values
- * "" Spool in default queue
- * "\\spool\queue" Spool in "queue"
- * "|command" open an output pipe using popen()
- * "filename" open filename using fopen()
- * "port" open port using fopen()
- */
- FILE *
- gp_open_printer(char fname[gp_file_name_sizeof], int binary_mode)
- {
- FILE *pfile;
-
- if ((strlen(fname) == 0) || is_os2_spool(fname)) {
- if (isos2) {
- /* default or spool */
- if (pm_spool(NULL, fname)) /* check if spool queue valid */
- return NULL;
- pfile = gp_open_scratch_file(gp_scratch_file_name_prefix,
- pm_prntmp, (binary_mode ? "wb" : "w"));
- } else
- pfile = fopen("PRN", (binary_mode ? "wb" : "w"));
- } else if ((isos2) && (fname[0] == '|'))
- /* pipe */
- pfile = popen(fname + 1, (binary_mode ? "wb" : "w"));
- else
- /* normal file or port */
- pfile = fopen(fname, (binary_mode ? "wb" : "w"));
-
- if (pfile == (FILE *) NULL)
- return (FILE *) NULL;
- if (!isos2)
- gp_set_file_binary(fileno(pfile), binary_mode);
- return pfile;
- }
-
- /* Close the connection to the printer. */
- void
- gp_close_printer(FILE * pfile, const char *fname)
- {
- if (isos2 && (fname[0] == '|'))
- pclose(pfile);
- else
- fclose(pfile);
-
- if ((strlen(fname) == 0) || is_os2_spool(fname)) {
- /* spool temporary file */
- pm_spool(pm_prntmp, fname);
- unlink(pm_prntmp);
- }
- }
-
- /* ------ File accessing -------- */
-
- /* Set a file into binary or text mode. */
- int
- gp_setmode_binary(FILE * pfile, bool binary)
- {
- gp_set_file_binary(fileno(pfile), binary);
- return 0;
- }
-
- /* ------ Printer Spooling ------ */
- #ifndef NERR_BufTooSmall
- #define NERR_BufTooSmall 2123 /* For SplEnumQueue */
- #endif
-
- /* If queue_name is NULL, list available queues */
- /* If strlen(queue_name)==0, return default queue and driver name */
- /* If queue_name supplied, return driver_name */
- /* returns 0 if OK, non-zero for error */
- private int
- pm_find_queue(char *queue_name, char *driver_name)
- {
- SPLERR splerr;
- USHORT jobCount;
- ULONG cbBuf;
- ULONG cTotal;
- ULONG cReturned;
- ULONG cbNeeded;
- ULONG ulLevel;
- ULONG i;
- PSZ pszComputerName;
- PBYTE pBuf;
- PPRQINFO3 prq;
-
- ulLevel = 3L;
- pszComputerName = (PSZ) NULL;
- splerr = SplEnumQueue(pszComputerName, ulLevel, pBuf, 0L, /* cbBuf */
- &cReturned, &cTotal,
- &cbNeeded, NULL);
- if (splerr == ERROR_MORE_DATA || splerr == NERR_BufTooSmall) {
- if (!DosAllocMem((PVOID) & pBuf, cbNeeded,
- PAG_READ | PAG_WRITE | PAG_COMMIT)) {
- cbBuf = cbNeeded;
- splerr = SplEnumQueue(pszComputerName, ulLevel, pBuf, cbBuf,
- &cReturned, &cTotal,
- &cbNeeded, NULL);
- if (splerr == NO_ERROR) {
- /* Set pointer to point to the beginning of the buffer. */
- prq = (PPRQINFO3) pBuf;
-
- /* cReturned has the count of the number of PRQINFO3 structures. */
- for (i = 0; i < cReturned; i++) {
- if (queue_name) {
- /* find queue name and return driver name */
- if (strlen(queue_name) == 0) { /* use default queue */
- if (prq->fsType & PRQ3_TYPE_APPDEFAULT)
- strcpy(queue_name, prq->pszName);
- }
- if (strcmp(prq->pszName, queue_name) == 0) {
- char *p;
-
- for (p = prq->pszDriverName; *p && (*p != '.'); p++)
- /* do nothing */ ;
- *p = '\0'; /* truncate at '.' */
- if (driver_name != NULL)
- strcpy(driver_name, prq->pszDriverName);
- DosFreeMem((PVOID) pBuf);
- return 0;
- }
- } else {
- /* list queue details */
- if (prq->fsType & PRQ3_TYPE_APPDEFAULT)
- fprintf(gs_stdout, " %s (DEFAULT)\n", prq->pszName);
- else
- fprintf(gs_stdout, " %s\n", prq->pszName);
- }
- prq++;
- } /*endfor cReturned */
- }
- DosFreeMem((PVOID) pBuf);
- }
- }
- /* end if Q level given */
- else {
- /* If we are here we had a bad error code. Print it and some other info. */
- fprintf(gs_stdout, "SplEnumQueue Error=%ld, Total=%ld, Returned=%ld, Needed=%ld\n",
- splerr, cTotal, cReturned, cbNeeded);
- }
- if (splerr)
- return splerr;
- if (queue_name)
- return -1;
- return 0;
- }
-
-
- /* return TRUE if queue looks like a valid OS/2 queue name */
- private int
- is_os2_spool(const char *queue)
- {
- char *prefix = "\\\\spool\\"; /* 8 characters long */
- int i;
-
- for (i = 0; i < 8; i++) {
- if (prefix[i] == '\\') {
- if ((*queue != '\\') && (*queue != '/'))
- return FALSE;
- } else if (tolower(*queue) != prefix[i])
- return FALSE;
- queue++;
- }
- return TRUE;
- }
-
- #define PRINT_BUF_SIZE 16384
-
- /* Spool file to queue */
- /* return 0 if successful, non-zero if error */
- /* if filename is NULL, return 0 if spool queue is valid, non-zero if error */
- private int
- pm_spool(char *filename, const char *queue)
- {
- HSPL hspl;
- PDEVOPENSTRUC pdata;
- PSZ pszToken = "*";
- ULONG jobid;
- BOOL rc;
- char queue_name[256];
- char driver_name[256];
- char *buffer;
- FILE *f;
- int count;
-
- if (strlen(queue) != 0) {
- /* queue specified */
- strcpy(queue_name, queue + 8); /* skip over \\spool\ */
- } else {
- /* get default queue */
- queue_name[0] = '\0';
- }
- if (pm_find_queue(queue_name, driver_name)) {
- /* error, list valid queue names */
- fprintf(gs_stdout, "Invalid queue name. Use one of:\n");
- pm_find_queue(NULL, NULL);
- return 1;
- }
- if (!filename)
- return 0; /* we were only asked to check the queue */
-
-
- if ((buffer = malloc(PRINT_BUF_SIZE)) == (char *)NULL) {
- fprintf(gs_stdout, "Out of memory in pm_spool\n");
- return 1;
- }
- if ((f = fopen(filename, "rb")) == (FILE *) NULL) {
- free(buffer);
- fprintf(gs_stdout, "Can't open temporary file %s\n", filename);
- return 1;
- }
- /* Allocate memory for pdata */
- if (!DosAllocMem((PVOID) & pdata, sizeof(DEVOPENSTRUC),
- (PAG_READ | PAG_WRITE | PAG_COMMIT))) {
- /* Initialize elements of pdata */
- pdata->pszLogAddress = queue_name;
- pdata->pszDriverName = driver_name;
- pdata->pdriv = NULL;
- pdata->pszDataType = "PM_Q_RAW";
- pdata->pszComment = "Ghostscript";
- pdata->pszQueueProcName = NULL;
- pdata->pszQueueProcParams = NULL;
- pdata->pszSpoolerParams = NULL;
- pdata->pszNetworkParams = NULL;
-
- hspl = SplQmOpen(pszToken, 4L, (PQMOPENDATA) pdata);
- if (hspl == SPL_ERROR) {
- fprintf(gs_stdout, "SplQmOpen failed.\n");
- DosFreeMem((PVOID) pdata);
- free(buffer);
- fclose(f);
- return 1; /* failed */
- }
- rc = SplQmStartDoc(hspl, "Ghostscript");
- if (!rc) {
- fprintf(gs_stdout, "SplQmStartDoc failed.\n");
- DosFreeMem((PVOID) pdata);
- free(buffer);
- fclose(f);
- return 1;
- }
- /* loop, copying file to queue */
- while (rc && (count = fread(buffer, 1, PRINT_BUF_SIZE, f)) != 0) {
- rc = SplQmWrite(hspl, count, buffer);
- if (!rc)
- fprintf(gs_stdout, "SplQmWrite failed.\n");
- }
- free(buffer);
- fclose(f);
-
- if (!rc) {
- fprintf(gs_stdout, "Aborting Spooling.\n");
- SplQmAbort(hspl);
- } else {
- SplQmEndDoc(hspl);
- rc = SplQmClose(hspl);
- if (!rc)
- fprintf(gs_stdout, "SplQmClose failed.\n");
- }
- } else
- rc = 0; /* no memory */
- return !rc;
- }
-
- /* ------ File naming and accessing ------ */
-
- /* Create and open a scratch file with a given name prefix. */
- /* Write the actual file name at fname. */
- FILE *
- gp_open_scratch_file(const char *prefix, char fname[gp_file_name_sizeof],
- const char *mode)
- {
- #ifdef __IBMC__
- char *temp = getenv("TMPDIR");
- char *tname;
-
- if (temp == 0)
- temp = getenv("TEMP");
- *fname = 0;
- tname = _tempnam(temp, (char *)prefix);
- if (tname) {
- /****** SHOULD DO A LENGTH CHECK ******/
- strcpy(fname, tname);
- free(tname);
- }
- #else
- /* The -7 is for XXXXXX plus a possible final \. */
- int len = gp_file_name_sizeof - strlen(prefix) - 7;
-
- if (gp_gettmpdir(fname, &len) != 0)
- *fname = 0;
- else {
- char last = '\\';
- char *temp;
-
- /* Prevent X's in path from being converted by mktemp. */
- for (temp = fname; *temp; temp++)
- *temp = last = tolower(*temp);
- switch (last) {
- default:
- strcat(fname, "\\");
- case ':':
- case '\\':
- ;
- }
- }
- strcat(fname, prefix);
- strcat(fname, "XXXXXX");
- mktemp(fname);
- #endif
- return gp_fopentemp(fname, mode);
- }
-
- /* Open a file with the given name, as a stream of uninterpreted bytes. */
- FILE *
- gp_fopen(const char *fname, const char *mode)
- {
- return fopen(fname, mode);
- }
-
- #ifdef __DLL__
-
- /* The DLL version must not be allowed direct access to stdin and stdout */
- /* Instead these are redirected to the gsdll_callback */
- #include "gsdll.h"
- #include <stdarg.h>
-
- /* for redirecting stdin/out/err */
- #include "stream.h"
- #include "gxiodev.h" /* must come after stream.h */
-
-
- /* ====== Substitute for stdio ====== */
-
- /* this code has been derived from gp_mswin.c */
-
- /* Forward references */
- private stream_proc_process(pm_std_read_process);
- private stream_proc_process(pm_std_write_process);
- private stream_proc_available(pm_std_available);
-
- /* Use a pseudo IODevice to get pm_stdio_init called at the right time. */
- /* This is bad architecture; we'll fix it later. */
- private iodev_proc_init(pm_stdio_init);
- const gx_io_device gs_iodev_wstdio = {
- /* The name is null to keep this from showing up as a resource. */
- 0, "Special",
- {pm_stdio_init, iodev_no_open_device,
- iodev_no_open_file, iodev_no_fopen, iodev_no_fclose,
- iodev_no_delete_file, iodev_no_rename_file,
- iodev_no_file_status, iodev_no_enumerate_files
- }
- };
-
- /* Discard the contents of the buffer when reading. */
- void
- pm_std_read_reset(stream * s)
- {
- s_std_read_reset(s);
- s->end_status = 0;
- }
-
- /* Define alternate 'open' routines for our stdin/out/err streams. */
-
- extern const gx_io_device gs_iodev_stdin;
- private int
- pm_stdin_open(gx_io_device * iodev, const char *access, stream ** ps,
- gs_memory_t * mem)
- {
- int code = gs_iodev_stdin.procs.open_device(iodev, access, ps, mem);
- stream *s = *ps;
-
- if (code != 1)
- return code;
- s->procs.reset = pm_std_read_reset;
- s->procs.process = pm_std_read_process;
- s->procs.available = pm_std_available;
- s->file = NULL;
- return 0;
- }
-
- extern const gx_io_device gs_iodev_stdout;
- private int
- pm_stdout_open(gx_io_device * iodev, const char *access, stream ** ps,
- gs_memory_t * mem)
- {
- int code = gs_iodev_stdout.procs.open_device(iodev, access, ps, mem);
- stream *s = *ps;
-
- if (code != 1)
- return code;
- s->procs.process = pm_std_write_process;
- s->procs.available = pm_std_available;
- s->file = NULL;
- return 0;
- }
-
- extern const gx_io_device gs_iodev_stderr;
- private int
- pm_stderr_open(gx_io_device * iodev, const char *access, stream ** ps,
- gs_memory_t * mem)
- {
- int code = gs_iodev_stderr.procs.open_device(iodev, access, ps, mem);
- stream *s = *ps;
-
- if (code != 1)
- return code;
- s->procs.process = pm_std_write_process;
- s->procs.available = pm_std_available;
- s->file = NULL;
- return 0;
- }
-
- /* Patch stdin/out/err to use our windows. */
- private int
- pm_stdio_init(gx_io_device * iodev, gs_memory_t * mem)
- {
- /* If stdxxx is the console, replace the 'open' routines, */
- /* which haven't gotten called yet. */
-
- if (gp_file_is_console(gs_stdin))
- gs_findiodevice((const byte *)"%stdin", 6)->procs.open_device =
- pm_stdin_open;
-
- if (gp_file_is_console(gs_stdout))
- gs_findiodevice((const byte *)"%stdout", 7)->procs.open_device =
- pm_stdout_open;
-
- if (gp_file_is_console(gs_stderr))
- gs_findiodevice((const byte *)"%stderr", 7)->procs.open_device =
- pm_stderr_open;
-
- return 0;
- }
-
-
- /* We should really use a private buffer for line reading, */
- /* because we can't predict the size of the supplied input area.... */
- private int
- pm_std_read_process(stream_state * st, stream_cursor_read * ignore_pr,
- stream_cursor_write * pw, bool last)
- {
- int count = pw->limit - pw->ptr;
-
- if (count == 0) /* empty buffer */
- return 1;
-
- /* callback to get more input */
- count = (*pgsdll_callback) (GSDLL_STDIN, pw->ptr + 1, count);
- if (count == 0) {
- /* EOF */
- /* what should we do? */
- return EOFC;
- }
- pw->ptr += count;
- return 1;
- }
-
- private int
- pm_std_available(register stream * s, long *pl)
- {
- *pl = -1; // EOF, since we can't do it
- return 0; // OK
- }
-
-
- private int
- pm_std_write_process(stream_state * st, stream_cursor_read * pr,
- stream_cursor_write * ignore_pw, bool last)
- {
- uint count = pr->limit - pr->ptr;
-
- (*pgsdll_callback) (GSDLL_STDOUT, (char *)(pr->ptr + 1), count);
- pr->ptr = pr->limit;
- return 0;
- }
-
- /* This is used instead of the stdio version. */
- /* The declaration must be identical to that in <stdio.h>. */
- #ifdef __EMX__
- int
- fprintf(FILE * file, __const__ char *fmt,...)
- #else
- int
- fprintf(FILE * file, const char *fmt,...)
- #endif
- {
- int count;
- va_list args;
-
- va_start(args, fmt);
- if (gp_file_is_console(file)) {
- char buf[1024];
-
- count = vsprintf(buf, fmt, args);
- (*pgsdll_callback) (GSDLL_STDOUT, buf, count);
- } else {
- count = vfprintf(file, fmt, args);
- }
- va_end(args);
- return count;
- }
- #endif /* __DLL__ */
-